﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Utiles.Persistencia;
using System.Data.SqlClient;
using EntidadesDeNegocio;
using Utiles.Excepcion;

namespace PersistenciaSql
{
    public class BrokerComponentes:Broker
    {
        public override void Insertar(ObjetoPersistente obj)
        {
            int oid = ObtenerUltimoOid() + 1;
            Componente comp = (Componente)obj;
            SqlConnection conn = ConexionBDManejador.CreaConexion();
            List<Componente> listCompRobot = new List<Componente>();
            string sql = @"Insert into Componentes (Oid,Modelo,NumeroSerie,Descripcion,Medio,Costo,Cantidad,FechaService,FechaCreacion,Profundidad,Temperatura,Altitud,Velocidad,Eliminado,TipoComponente) " +
                        " values (@Oid,@Modelo,@NumeroSerie,@Descripcion,@Medio,@Costo,@Cantidad,@FechaService,@FechaCreacion,@Profundidad,@Temperatura,@Altitud,@Velocidad,@Eliminado,@TipoComponente)";
            SqlCommand comm = new SqlCommand(sql, conn);
            comm.Parameters.Add("@Oid",System.Data.SqlDbType.Int).Value=oid;
            comm.Parameters.Add("@Modelo",System.Data.SqlDbType.Text).Value = comp.Modelo;
            comm.Parameters.Add("@NumeroSerie",System.Data.SqlDbType.Text).Value = comp.NumeroSerie;
            comm.Parameters.Add("@Medio",System.Data.SqlDbType.Text).Value = comp.Medio.ToString();
            comm.Parameters.Add("@Costo",System.Data.SqlDbType.Decimal).Value = comp.Costo;
            comm.Parameters.Add("@Cantidad",System.Data.SqlDbType.Int).Value = comp.Cantidad;
            comm.Parameters.Add("@FechaService",System.Data.SqlDbType.DateTime).Value = comp.FechaService;
            comm.Parameters.Add("@FechaCreacion",System.Data.SqlDbType.DateTime).Value = comp.FechaCreacion;
            comm.Parameters.Add("@Descripcion", System.Data.SqlDbType.Text).Value = comp.Descripcion;
            comm.Parameters.Add("@Eliminado", System.Data.SqlDbType.Bit).Value = false;
            if (comp is PiezaAcuatica)
            {
                comm.Parameters.Add("@Profundidad", System.Data.SqlDbType.Decimal).Value = ((PiezaAcuatica)comp).Profundidad;
                comm.Parameters.Add("@Temperatura", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@Altitud", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@Velocidad", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@TipoComponente", System.Data.SqlDbType.Text).Value = TipoComponente.PiezaAcuatica.ToString();  
               
            }
            if (comp is PiezaAerea)
            {
                comm.Parameters.Add("@Profundidad", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@Temperatura", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@Altitud", System.Data.SqlDbType.Decimal).Value = ((PiezaAerea)comp).Altitud;
                comm.Parameters.Add("@Velocidad", System.Data.SqlDbType.Decimal).Value = ((PiezaAerea)comp).Velocidad;
                comm.Parameters.Add("@TipoComponente", System.Data.SqlDbType.Text).Value = TipoComponente.PiezaAerea.ToString();
            }
            if (comp is PiezaTerrestre)
            {
                comm.Parameters.Add("@Profundidad", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@Temperatura", System.Data.SqlDbType.Decimal).Value = ((PiezaTerrestre)comp).Temperatura;
                comm.Parameters.Add("@Altitud", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@Velocidad", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@TipoComponente", System.Data.SqlDbType.Text).Value = TipoComponente.PiezaTerrestre.ToString();
            }
            if (comp.GetTipo() == TipoComponente.Robot)
            {
                comm.Parameters.Add("@Profundidad", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@Temperatura", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@Altitud", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@Velocidad", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@TipoComponente", System.Data.SqlDbType.Text).Value = TipoComponente.Robot.ToString();
                listCompRobot = ((Robot)comp).ListaComposicion;
            }
            try
            {
                conn.Open();
                comm.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw new BDExcepcion("Error al insertar componente: "+ex.Message);
            }
            finally
            {
                conn.Close();
            }
            if (listCompRobot != null && listCompRobot.Count > 0)
            {
                string sqlAditional = "Insert into ComponenteComp (IdComponentePadre,IdComponenteHijo,CantidadComp) values (@IdComponentePadre,@IdComponenteHijo,@CantidadComp)";
                SqlCommand commAditional = new SqlCommand(sqlAditional, conn);
                commAditional.Parameters.Add("@IdComponentePadre", System.Data.SqlDbType.Int);
                commAditional.Parameters.Add("@IdComponenteHijo", System.Data.SqlDbType.Int);
                commAditional.Parameters.Add("@CantidadComp", System.Data.SqlDbType.Int);
                try
                {
                    conn.Open();
                    foreach (Componente c in listCompRobot)
                    {
                        commAditional.Parameters["@IdComponentePadre"].Value = oid;
                        commAditional.Parameters["@IdComponenteHijo"].Value = c.Oid;
                        commAditional.Parameters["@CantidadComp"].Value = c.Cantidad;
                        commAditional.ExecuteNonQuery();
                    }
                }
                catch (Exception ex)
                {
                    throw new BDExcepcion("Error al guardar componente de Robot: " + ex.Message);
                }
                finally
                {
                    conn.Close();
                }
            }
            

        }

        public override void Actualizar(ObjetoPersistente obj)
        {
            string sql = @"Update Componentes set " +
                          "Modelo=@Modelo " +
                          ", NumeroSerie = @NumeroSerie " +
                          ", Descripcion = @Descripcion" +
                          ", Medio = @Medio" +
                          ", Costo = @Costo" +
                          ", Cantidad = @Cantidad" +
                          ", FechaService = @FechaService" +
                          ", FechaCreacion = @FechaCreacion" +
                          ", Profundidad = @Profundidad " +
                          ", Temperatura = @Temperatura " +
                          ", Altitud = @Altitud " +
                          ", Velocidad = @Velocidad" +
                          ", TipoComponente = @TipoComponente " +
                          " Where Oid = @Oid ";
            SqlConnection conn = ConexionBDManejador.CreaConexion();
            SqlCommand comm = new SqlCommand(sql, conn);
            Componente comp = (Componente)obj;
            comm.Parameters.Add("@Oid", System.Data.SqlDbType.Int).Value = comp.Oid;
            comm.Parameters.Add("@Modelo", System.Data.SqlDbType.Text).Value = comp.Modelo;
            comm.Parameters.Add("@NumeroSerie", System.Data.SqlDbType.Text).Value = comp.NumeroSerie;
            comm.Parameters.Add("@Medio", System.Data.SqlDbType.Text).Value = comp.Medio.ToString();
            comm.Parameters.Add("@Costo", System.Data.SqlDbType.Decimal).Value = comp.Costo;
            comm.Parameters.Add("@Cantidad", System.Data.SqlDbType.Int).Value = comp.Cantidad;
            comm.Parameters.Add("@FechaService", System.Data.SqlDbType.DateTime).Value = comp.FechaService;
            comm.Parameters.Add("@FechaCreacion", System.Data.SqlDbType.DateTime).Value = comp.FechaCreacion;
            comm.Parameters.Add("@Descripcion", System.Data.SqlDbType.Text).Value = comp.Descripcion;            
            if (comp is PiezaAcuatica)
            {
                comm.Parameters.Add("@Profundidad", System.Data.SqlDbType.Decimal).Value = ((PiezaAcuatica)comp).Profundidad;
                comm.Parameters.Add("@Temperatura", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@Altitud", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@Velocidad", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@TipoComponente", System.Data.SqlDbType.Text).Value = TipoComponente.PiezaAcuatica.ToString();

            }
            if (comp is PiezaAerea)
            {
                comm.Parameters.Add("@Profundidad", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@Temperatura", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@Altitud", System.Data.SqlDbType.Decimal).Value = ((PiezaAerea)comp).Altitud;
                comm.Parameters.Add("@Velocidad", System.Data.SqlDbType.Decimal).Value = ((PiezaAerea)comp).Velocidad;
                comm.Parameters.Add("@TipoComponente", System.Data.SqlDbType.Text).Value = TipoComponente.PiezaAerea.ToString();
            }
            if (comp is PiezaTerrestre)
            {
                comm.Parameters.Add("@Profundidad", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@Temperatura", System.Data.SqlDbType.Decimal).Value = ((PiezaTerrestre)comp).Temperatura;
                comm.Parameters.Add("@Altitud", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@Velocidad", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@TipoComponente", System.Data.SqlDbType.Text).Value = TipoComponente.PiezaTerrestre.ToString();
            }
            if (comp.GetTipo() == TipoComponente.Robot)
            {
                comm.Parameters.Add("@Profundidad", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@Temperatura", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@Altitud", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@Velocidad", System.Data.SqlDbType.Decimal).Value = DBNull.Value;
                comm.Parameters.Add("@TipoComponente", System.Data.SqlDbType.Text).Value = TipoComponente.Robot.ToString();
            }
            try
            {
                conn.Open();
                comm.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw new BDExcepcion("Error al actualizar componente: " + ex.Message);
            }
            finally
            {
                conn.Close();
            }           
        }

        public override void Borrar(ObjetoPersistente obj)
        {
            string sql = "Update Componentes Set Eliminado = @Eliminado Where Oid= @Oid";
            SqlConnection conn = ConexionBDManejador.CreaConexion();
            SqlCommand comm = new SqlCommand(sql, conn);
            Componente comp = (Componente)obj;
            comm.Parameters.Add("@Oid", System.Data.SqlDbType.Int).Value = comp.Oid;
            comm.Parameters.Add("@Eliminado", System.Data.SqlDbType.Bit).Value = true;
            try
            {
                conn.Open();
                comm.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw new BDExcepcion("Error al borrar componente: " + ex.Message);
            }
            finally
            {
                conn.Close();
            }        
        }

        public override List<ObjetoPersistente> SeleccionaTodo()
        {
            string sql = "Select * From Componentes Where Eliminado = @Eliminado";
            SqlConnection conn = ConexionBDManejador.CreaConexion();
            SqlCommand comm = new SqlCommand(sql, conn);            
            comm.Parameters.Add("@Eliminado", System.Data.SqlDbType.Bit).Value = false;
            List<ObjetoPersistente> list= new List<ObjetoPersistente>();           
           
            try
            {
                conn.Open();
                using (SqlDataReader reader = comm.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        string tipo = reader.GetString(reader.GetOrdinal("TipoComponente"));
                        if (tipo == TipoComponente.PiezaAcuatica.ToString())
                        {
                            PiezaAcuatica comp = new PiezaAcuatica();
                            comp.Oid = reader.GetInt32(reader.GetOrdinal("Oid"));
                            comp.NumeroSerie = reader.GetString(reader.GetOrdinal("NumeroSerie"));
                            comp.Modelo = reader.GetString(reader.GetOrdinal("Modelo"));
                            comp.Medio = MedioComponente.Acuatico;
                            comp.Cantidad = reader.GetInt32(reader.GetOrdinal("Cantidad"));
                            comp.Costo = reader.GetDecimal(reader.GetOrdinal("Costo"));
                            comp.Descripcion = reader.GetString(reader.GetOrdinal("Descripcion"));
                            comp.FechaCreacion = reader.GetDateTime(reader.GetOrdinal("FechaCreacion"));
                            comp.FechaService = reader.GetDateTime(reader.GetOrdinal("FechaService"));
                            comp.Profundidad = reader.GetDecimal(reader.GetOrdinal("Profundidad"));
                            list.Add(comp);
                        }
                        if (tipo == TipoComponente.PiezaAerea.ToString())
                        {
                            PiezaAerea comp = new PiezaAerea();
                            comp.Oid = reader.GetInt32(reader.GetOrdinal("Oid"));
                            comp.NumeroSerie = reader.GetString(reader.GetOrdinal("NumeroSerie"));
                            comp.Modelo = reader.GetString(reader.GetOrdinal("Modelo"));
                            comp.Medio = MedioComponente.Aereo;
                            comp.Cantidad = reader.GetInt32(reader.GetOrdinal("Cantidad"));
                            comp.Costo = reader.GetDecimal(reader.GetOrdinal("Costo"));
                            comp.Descripcion = reader.GetString(reader.GetOrdinal("Descripcion"));
                            comp.FechaCreacion = reader.GetDateTime(reader.GetOrdinal("FechaCreacion"));
                            comp.FechaService = reader.GetDateTime(reader.GetOrdinal("FechaService"));
                            comp.Altitud = reader.GetDecimal(reader.GetOrdinal("Altitud"));
                            comp.Velocidad = reader.GetDecimal(reader.GetOrdinal("Velocidad"));
                            list.Add(comp);
                        }
                        if (tipo == TipoComponente.PiezaTerrestre.ToString())
                        {
                            PiezaTerrestre comp = new PiezaTerrestre();
                            comp.Oid = reader.GetInt32(reader.GetOrdinal("Oid"));
                            comp.NumeroSerie = reader.GetString(reader.GetOrdinal("NumeroSerie"));
                            comp.Modelo = reader.GetString(reader.GetOrdinal("Modelo"));
                            comp.Medio = MedioComponente.Terrestre;
                            comp.Cantidad = reader.GetInt32(reader.GetOrdinal("Cantidad"));
                            comp.Costo = reader.GetDecimal(reader.GetOrdinal("Costo"));
                            comp.Descripcion = reader.GetString(reader.GetOrdinal("Descripcion"));
                            comp.FechaCreacion = reader.GetDateTime(reader.GetOrdinal("FechaCreacion"));
                            comp.FechaService = reader.GetDateTime(reader.GetOrdinal("FechaService"));
                            comp.Temperatura = reader.GetDecimal(reader.GetOrdinal("Temperatura"));
                            list.Add(comp);
                        }
                        if (tipo == TipoComponente.Robot.ToString())
                        {
                            Robot comp = new Robot();
                            comp.Oid = reader.GetInt32(reader.GetOrdinal("Oid"));
                            comp.NumeroSerie = reader.GetString(reader.GetOrdinal("NumeroSerie"));
                            comp.Modelo = reader.GetString(reader.GetOrdinal("Modelo"));
                            comp.Cantidad = reader.GetInt32(reader.GetOrdinal("Cantidad"));
                            comp.Costo = reader.GetDecimal(reader.GetOrdinal("Costo"));
                            comp.Descripcion = reader.GetString(reader.GetOrdinal("Descripcion"));
                            comp.FechaCreacion = reader.GetDateTime(reader.GetOrdinal("FechaCreacion"));
                            comp.FechaService = reader.GetDateTime(reader.GetOrdinal("FechaService"));
                            comp.ListaComposicion = new List<Componente>();
                            comp.ListaComposicion = ListaComposicion(comp.Oid, conn);
                            list.Add(comp);
                        }
                    }
                }
                
                return list;
            }
            catch (Exception ex)
            {
                
                throw new BDExcepcion("Error al seleccionar los componentes: " + ex.Message);
            }
            finally 
            {
                conn.Close();
            }

        }

        public override ObjetoPersistente SeleccionaUno(ObjetoPersistente obj)
        {
            throw new NotImplementedException();
        }        
        public override int ObtenerUltimoOid()
        {
            string sql = "Select Max(Oid) From Componentes";
            SqlConnection con = ConexionBDManejador.CreaConexion();
            SqlCommand comm = new SqlCommand(sql,con);
            try
            {
                con.Open();
                object o = comm.ExecuteScalar();
                if (o.ToString() == string.Empty)
                    return 0;
                else
                    return (int)o;  
            }
            catch (Exception ex)
            {
                throw new BDExcepcion("Error para obtener el ultimo id de la tabla componente: "+ex.Message);
            }
            finally 
            {
                con.Close();
            }           
                      
        }
        /// <summary>
        /// Retorna la lista de composicion del robot
        /// </summary>
        /// <param name="oidPadre"></param>
        /// <param name="conn"></param>
        /// <returns></returns>
        private List<Componente> ListaComposicion(int oidPadre,SqlConnection con)
        {
            List<Componente> listaResultado = new List<Componente>();
            string sqladitional = "Select c.*,cc.CantidadComp From Componentes c INNER JOIN ComponenteComp cc ON c.Oid=cc.IdComponenteHijo Where cc.IdComponentePadre=@IdComponentePadre ";
            SqlCommand comm1 = con.CreateCommand();
            comm1.CommandText = sqladitional;
            comm1.CommandType = System.Data.CommandType.Text;
           
            try
            {
                
                comm1.Parameters.Add("@IdComponentePadre", System.Data.SqlDbType.Int).Value = oidPadre;
                using (SqlDataReader reader1 = comm1.ExecuteReader())
                {
                    while (reader1.Read())
                    {
                        string tipo = reader1.GetString(reader1.GetOrdinal("TipoComponente"));
                        if (tipo == TipoComponente.PiezaAcuatica.ToString())
                        {
                            PiezaAcuatica comp = new PiezaAcuatica();
                            comp.Oid = reader1.GetInt32(reader1.GetOrdinal("Oid"));
                            comp.NumeroSerie = reader1.GetString(reader1.GetOrdinal("NumeroSerie"));
                            comp.Modelo = reader1.GetString(reader1.GetOrdinal("Modelo"));
                            comp.Medio = MedioComponente.Acuatico;
                            comp.Cantidad = reader1.GetInt32(reader1.GetOrdinal("CantidadComp"));
                            comp.Costo = reader1.GetDecimal(reader1.GetOrdinal("Costo"));
                            comp.Descripcion = reader1.GetString(reader1.GetOrdinal("Descripcion"));
                            comp.FechaCreacion = reader1.GetDateTime(reader1.GetOrdinal("FechaCreacion"));
                            comp.FechaService = reader1.GetDateTime(reader1.GetOrdinal("FechaService"));
                            comp.Profundidad = reader1.GetDecimal(reader1.GetOrdinal("Profundidad"));
                            listaResultado.Add(comp);
                        }
                        if (tipo == TipoComponente.PiezaAerea.ToString())
                        {
                            PiezaAerea comp = new PiezaAerea();
                            comp.Oid = reader1.GetInt32(reader1.GetOrdinal("Oid"));
                            comp.NumeroSerie = reader1.GetString(reader1.GetOrdinal("NumeroSerie"));
                            comp.Modelo = reader1.GetString(reader1.GetOrdinal("Modelo"));
                            comp.Medio = MedioComponente.Acuatico;
                            comp.Cantidad = reader1.GetInt32(reader1.GetOrdinal("CantidadComp"));
                            comp.Costo = reader1.GetDecimal(reader1.GetOrdinal("Costo"));
                            comp.Descripcion = reader1.GetString(reader1.GetOrdinal("Descripcion"));
                            comp.FechaCreacion = reader1.GetDateTime(reader1.GetOrdinal("FechaCreacion"));
                            comp.FechaService = reader1.GetDateTime(reader1.GetOrdinal("FechaService"));
                            comp.Altitud = reader1.GetDecimal(reader1.GetOrdinal("Altitud"));
                            comp.Velocidad = reader1.GetDecimal(reader1.GetOrdinal("Velocidad"));
                            listaResultado.Add(comp);
                        }
                        if (tipo == TipoComponente.PiezaTerrestre.ToString())
                        {
                            PiezaTerrestre comp = new PiezaTerrestre();
                            comp.Oid = reader1.GetInt32(reader1.GetOrdinal("Oid"));
                            comp.NumeroSerie = reader1.GetString(reader1.GetOrdinal("NumeroSerie"));
                            comp.Modelo = reader1.GetString(reader1.GetOrdinal("Modelo"));
                            comp.Medio = MedioComponente.Acuatico;
                            comp.Cantidad = reader1.GetInt32(reader1.GetOrdinal("CantidadComp"));
                            comp.Costo = reader1.GetDecimal(reader1.GetOrdinal("Costo"));
                            comp.Descripcion = reader1.GetString(reader1.GetOrdinal("Descripcion"));
                            comp.FechaCreacion = reader1.GetDateTime(reader1.GetOrdinal("FechaCreacion"));
                            comp.FechaService = reader1.GetDateTime(reader1.GetOrdinal("FechaService"));
                            comp.Temperatura = reader1.GetDecimal(reader1.GetOrdinal("Temperatura"));
                            listaResultado.Add(comp);
                        }
                        if (tipo == TipoComponente.Robot.ToString())
                        {
                            Robot comp = new Robot();
                            comp.Oid = reader1.GetInt32(reader1.GetOrdinal("Oid"));
                            comp.NumeroSerie = reader1.GetString(reader1.GetOrdinal("NumeroSerie"));
                            comp.Modelo = reader1.GetString(reader1.GetOrdinal("Modelo"));
                            comp.Medio = MedioComponente.Acuatico;
                            comp.Cantidad = reader1.GetInt32(reader1.GetOrdinal("CantidadComp"));
                            comp.Costo = reader1.GetDecimal(reader1.GetOrdinal("Costo"));
                            comp.Descripcion = reader1.GetString(reader1.GetOrdinal("Descripcion"));
                            comp.FechaCreacion = reader1.GetDateTime(reader1.GetOrdinal("FechaCreacion"));
                            comp.FechaService = reader1.GetDateTime(reader1.GetOrdinal("FechaService"));
                            comp.ListaComposicion = new List<Componente>();
                            comp.ListaComposicion = ListaComposicion(comp.Oid, con);
                            listaResultado.Add(comp);
                        }
                    }
                }
                
                return listaResultado;
            }
            catch (Exception ex)
            {
                
                throw new BDExcepcion("Error al seleccionar los componentes: " + ex.Message);
            }           
        }
    }
}
